﻿using System;
using System.Collections.Specialized;

namespace MyLib.Tools.AutoDbUnit {
	/// <summary>
	/// 
	/// </summary>
	class Program {
		/// <summary>
		/// 
		/// </summary>
		/// <param name="args"></param>
		static int Main(string[] args) {
			try {
				var section = System.Configuration.ConfigurationManager.GetSection("export") as ExportConfigurationSection;

				var ds = GetDataSetFromDb(
					section.ProviderName,
					section.ConnectionString,
					section.Tables.ToArray());

				WriteToFile(section.SchemaFileName, section.DataFileName, ds);

				Console.ForegroundColor = ConsoleColor.White;
				Console.WriteLine("Done.");

				Console.ResetColor();

				return 0;
			} catch (Exception e) {
				Console.ForegroundColor = ConsoleColor.Red;
				Console.Error.WriteLine(e);

				return 1;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="schemaFileName"></param>
		/// <param name="dataFileName"></param>
		/// <param name="ds"></param>
		private static void WriteToFile(string schemaFileName, string dataFileName, System.Data.DataSet ds) {
			Console.ForegroundColor = ConsoleColor.Gray;
			Console.WriteLine("Dumping schema file...");

			var xmlSettings = new System.Xml.XmlWriterSettings();
			xmlSettings.CheckCharacters = true;
			xmlSettings.CloseOutput = true;
			xmlSettings.ConformanceLevel = System.Xml.ConformanceLevel.Document;
			xmlSettings.Encoding = System.Text.Encoding.UTF8;
			xmlSettings.Indent = true;
			xmlSettings.IndentChars = "    ";
			xmlSettings.OmitXmlDeclaration = false;

			using (var fs = new System.IO.FileStream(
				schemaFileName,
				System.IO.FileMode.Create,
				System.IO.FileAccess.Write,
				System.IO.FileShare.None, 4 * 1024)) {

				var xw = System.Xml.XmlWriter.Create(fs, xmlSettings);

				ds.WriteXmlSchema(xw);

				fs.Flush();
				fs.Close();
			}

			Console.ForegroundColor = ConsoleColor.Gray;
			Console.WriteLine("Dumping data file...");

			using (var fs = new System.IO.FileStream(
				dataFileName,
				System.IO.FileMode.Create,
				System.IO.FileAccess.Write,
				System.IO.FileShare.None, 4 * 1024)) {

				var xw = System.Xml.XmlWriter.Create(fs, xmlSettings);

				ds.WriteXml(xw);

				fs.Flush();
				fs.Close();
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="providerName"></param>
		/// <param name="connectionString"></param>
		/// <param name="tables"></param>
		static System.Data.DataSet GetDataSetFromDb(string providerName, string connectionString, params string[] tables) {
			System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(providerName));

			providerName = providerName.ToLower().Trim();

			System.Data.Common.DbProviderFactory dbFactory;

			var quotePrefix = "";
			var quoteSuffix = "";

			if (providerName == "mysql") {
				dbFactory = System.Data.Common.DbProviderFactories.GetFactory("MySql.Data.MySqlClient");
				quotePrefix = "`";
				quoteSuffix = "`";
			} else if (providerName == "mssql") {
				dbFactory = System.Data.Common.DbProviderFactories.GetFactory("System.Data.SqlClient");
				quotePrefix = "[";
				quoteSuffix = "]";
			} else {
				throw new InvalidOperationException(
					string.Format("Unknown provider: \"{0}\".", providerName));
			}

			var ds = new System.Data.DataSet("TestData");
			ds.Namespace = "http://tempuri.org/TestData.xsd";

			var connection = dbFactory.CreateConnection();
			connection.ConnectionString = connectionString;
			using (connection) {
				var command = dbFactory.CreateCommand();
				command.Connection = connection;

				foreach (string table in tables) {
					command.CommandText = string.Format("select * from {0}{1}{2}", quotePrefix, table, quoteSuffix);

					Console.WriteLine("Fetching [{0}]...", table);

					var adapter = dbFactory.CreateDataAdapter();
					adapter.SelectCommand = command;
					adapter.Fill(ds, table);
				}
			}

			return ds;
		}
	} // end of Program.
}
